package com.lcf.framework.handler;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotSafeException;
import com.lcf.base.exception.ExceptionEnum;
import com.lcf.base.exception.SysException;
import com.lcf.base.model.R;
import feign.codec.DecodeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import java.util.stream.Collectors;

/**
 * 全局异常处理器
 *
 * @author lcf
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 基础异常
     */
    @ExceptionHandler(Exception.class)
    public R<Void> handleException(Exception e) {
        log.error(e.getMessage(), e);

        return R.fail();
    }

    /**
     * 业务异常
     */
    @ExceptionHandler(SysException.class)
    public R<Void> businessException(SysException e) {
        log.error(e.getMsg(), e);

        return R.fail(e);
    }

    /**
     * openfeign异常
     */
    @ExceptionHandler(DecodeException.class)
    public R<Void> handleException(DecodeException e) {
        log.error(e.getMessage(), e);

        //如果是自己封装的异常，则返回
        if (e.getCause() instanceof SysException sysException) {
            return R.fail(sysException);
        }

        return R.fail();
    }

    /**
     * 参数检查
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<Void> handleValidationExceptions(MethodArgumentNotValidException ex) {
        String msg = ex.getBindingResult().getAllErrors()
                .stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining("，"));

        log.error(msg, ex);

        return R.fail(msg);
    }

    /**
     * 登录异常
     */
    @ExceptionHandler(NotLoginException.class)
    public R<Void> notLoginException(NotLoginException e) {
        log.error(e.getMessage(), e);

        return R.fail(ExceptionEnum.NOT_LOGIN);
    }

    /**
     * 权限不足
     */
    @ExceptionHandler(NotPermissionException.class)
    public R<Void> notPermissionException(NotPermissionException e) {
        log.error(e.getMessage(), e);

        return R.fail(ExceptionEnum.NOT_PERMISSION);
    }

    /**
     * 上传文件过大
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public R<Void> handleMaxSizeException(MaxUploadSizeExceededException e) {
        log.error(e.getMessage(), e);

        return R.fail(ExceptionEnum.UPLOAD_FILE_TOO_LARGE);
    }

    /**
     * 二级认证
     */
    @ExceptionHandler(NotSafeException.class)
    public R<Void> notSafeException(NotSafeException e) {
        log.error(e.getMessage(), e);

        return R.fail(ExceptionEnum.SAFE_CHECK_FAIL);
    }
}
